package br.com.medvagas.comum.excecao;

import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.application.ProjectStage;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DefaultExceptionHandler extends ExceptionHandlerWrapper {
	
    private static final Log LOG = LogFactory.getLog(DefaultExceptionHandler.class);

    /** key for session scoped message detail */
    public static final String MESSAGE_DETAIL_KEY = "ip.client.jsftoolkit.messageDetail";

    private ExceptionHandler wrapped;

    public DefaultExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public ExceptionHandler getWrapped() {
        return this.wrapped;
    }

    @Override
    public void handle() throws FacesException {
//        if (fc.isProjectStage(ProjectStage.Development)) {
//            // Code for development mode. E.g. let the parent handle exceptions
//            getWrapped().handle();
//        } else {
            for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
                ExceptionQueuedEvent event = i.next();
                ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();

                String redirectPage = null;
                FacesContext fc = FacesContext.getCurrentInstance();
                Throwable t = context.getException();

                try {
                    if (t instanceof AbortProcessingException) {
                        // about AbortProcessingException see JSF 2 spec.
                        LOG.error("An unexpected exception has occurred by event listener(s)", t);
                        redirectPage = "/views/error.jsf?statusCode=jsftoolkit.exception.UncheckedException";
                        fc.getExternalContext().getSessionMap()
                            .put(DefaultExceptionHandler.MESSAGE_DETAIL_KEY, t.getLocalizedMessage());
                    } else if (t instanceof ViewExpiredException) {
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("View '" + ((ViewExpiredException) t).getViewId() + "' is expired", t);
                        }

//                        ApplicationConfiguration appConfiguration =
//                            (ApplicationConfiguration) FacesAccessor.accessManagedBean(
//                                ApplicationConfiguration.BEAN_NAME_APPLICATION_CONFIGURATION);
                        HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);
                        if (session != null) {
                            // should not happen
                            session.invalidate();
                        }

//                        if (appConfiguration.getBoolean(ConfigKeys.KEY_LOGOFF_2_LOGOUT_PAGE, false)) {
//                            // redirect to the specified logout page
//                            redirectPage = "/views/logout.jsf";
//                        } else {
//                            // redirect to the login page
//                            redirectPage = "";
//                        }
//                    } else if (t instanceof ServiceNotAvailableException) {
//                        LOG.error("'" + ((ServiceNotAvailableException) t).getServiceName() + "' is not available", t);
//                            redirectPage = "/views/error.jsf?statusCode=jsftoolkit.exception.ServiceNotAvailableException";
                    } else {
                        // custom handling of unexpected exceptions can be done in the method handleUnexpected
                        String messageKey = handleUnexpected(fc, t);
                        redirectPage = "/views/error.jsf?statusCode=" + messageKey;
                        fc.getExternalContext().getSessionMap()
                            .put(DefaultExceptionHandler.MESSAGE_DETAIL_KEY, t.getLocalizedMessage());
                    }
                } finally {
                    i.remove();
                }

//                SecurityPhaseListener spl = new SecurityPhaseListener();
//                spl.doRedirect(fc, redirectPage);

                break;
            }
//        }
    }

    protected String handleUnexpected(FacesContext facesContext, final Throwable t) {
        LOG.error("An unexpected internal error has occurred", t);

        return "jsftoolkit.exception.UncheckedException";
    }
}
